#include <Core/Commands.h>
#include <Core/BoxApi/ApiManager.h>

#include <boost/thread.hpp>
#include <iostream>

typedef std::list
		<
			std::pair
			<
				Core::ICommandPtr, 
				Core::BoxApi::IBoxConnectionPtr
			> 
		> MessagesType;

int sendLatency = 1, recvLatency = 3;
Core::BoxApi::ApiManagerParams const amParams = { 5, true };	
Core::BoxApi::ApiManager apiManager(amParams);
boost::mutex outLock;

void sendLoop() 
{
	for (;;) {
#if !defined(WIN32)
		sleep(sendLatency);
#else
#endif
		Core::BoxApi::BoxConnectionParams connArgs = { "127.0.0.1", "5999", "conn1", 0 };
		Core::BoxApi::IBoxConnectionPtr currConn = apiManager.connect(connArgs);
		apiManager.postMessage(currConn, Core::PingCommandPtr(new Core::PingCommand()));
		boost::mutex::scoped_lock lock(outLock);
		std::cout << "Message send to { 127.0.0.1, 5999, conn1, 0 }" << std::endl;
	}
}

void recvLoop() 
{
	for (;;) {
#if !defined(WIN32)
		sleep(recvLatency);
#else
#endif
		MessagesType messages = apiManager.getNextMessages(0 /* means all pending messages */ );
		for (MessagesType::iterator first = messages.begin(), last = messages.end(); 
			first != last;
			++first) 
		{
			Core::ICommandPtr command = first->first;
			Core::BoxApi::IBoxConnectionPtr currConn = first->second;
			if (command->getTag() == Core::ErrorCommand::tag) {
				Core::ErrorCommandPtr err = Core::commandCast<Core::ErrorCommand>(command);
				boost::mutex::scoped_lock lock(outLock);
				std::cerr << "Got error : " << err->getMessage() << ", message count : " << apiManager.getMessageCount() << std::endl;  
			}
			else {
				boost::mutex::scoped_lock lock(outLock);
				std::cout << "Got message : TAG " << command->getTag() << ", message count : " << apiManager.getMessageCount() << std::endl;
			}
		}
	} // loop
}

int main(int argc, char ** argv) 
try 
{
	boost::thread recv(&recvLoop), send(&sendLoop);
	recv.join(), send.join();

	return 0;
} 
catch (std::exception const & expt) 
{
	std::cerr << "Error : " << expt.what() << std::endl;
	return 1;
}

